package com.qianke.common;

import com.alibaba.fastjson.JSON;
import com.qianke.domain.Constants;
import com.qianke.domain.dto.LoginUserDto;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class RequestContext {

    private static final Logger logger = LoggerFactory.getLogger(RequestContext.class);

    private static ThreadLocal<HttpServletRequest> requestContext = new ThreadLocal<HttpServletRequest>();
    private static ThreadLocal<HttpServletResponse> responseContext = new ThreadLocal<HttpServletResponse>();
    private static ThreadLocal<Object> controllerContext = new ThreadLocal<Object>();

    private static RedisTemplate<String, String> redisTemplate;

    public static void init(HttpServletRequest request, HttpServletResponse response, Object controller) {
        setRequest(request);
        setResponse(response);
        setController(controller);

        refreshToken();
    }

    public static HttpSession getSession() {
        if (getRequest() == null) {
            return null;
        }
        return getRequest().getSession(true);
    }

    public static HttpServletRequest getRequest() {
        return requestContext.get();
    }

    public static HttpServletResponse getResponse() {
        return responseContext.get();
    }

    public static void setRequest(HttpServletRequest request) {
        requestContext.set(request);
    }

    public static void setResponse(HttpServletResponse response) {
        responseContext.set(response);
    }

    public static void setController(Object controller) {
        controllerContext.set(controller);
    }

    public <T> T getController() {
        return (T) controllerContext.get();
    }

    public static void clear() {
        requestContext.remove();
        responseContext.remove();
        controllerContext.remove();
    }

    public static String getParam(String name) {
        return requestContext.get().getParameter(name);
    }

    public static String getStr(String name) {
        return getStr(name, StringUtils.EMPTY);
    }

    public static String getStr(String name, String defaultValue) {
        String v = getParam(name);
        if (StringUtils.isBlank(v)) {
            return defaultValue;
        }

        return v;
    }

    public static Boolean getBoolean(String name, Boolean defaultValue) {
        String value = getParam(name);
        Boolean bool = BooleanUtils.toBooleanObject(value);
        if (bool == null) {
            return defaultValue;
        }

        return bool;
    }

    public static Boolean getBoolean(String name) {
        return getBoolean(name, null);
    }

    public static Integer getInteger(String name) {
        return getInteger(name, null);
    }

    public static Integer getInteger(String name, Integer defaultValue) {
        String value = getParam(name);
        if (StringUtils.isBlank(value)) {
            return defaultValue;
        }

        try {
            return Integer.valueOf(value);
        } catch (Exception e) {
            logger.info(e.getMessage());
        }

        return defaultValue;
    }

    public static String setLoginUser(LoginUserDto user) {
        String token = getRequest().getHeader("token");
        if (StringUtils.isBlank(token)) {
            token = UUID.randomUUID().toString();
        }
        RedisTemplate<String, String> redisTemplateDB = RedisUtils.setConnectionFactoryDB(RequestContext.redisTemplate, 0);
        redisTemplateDB.opsForValue().set(Constants.TOKEN_PREFIX + token, JSON.toJSONString(user), Constants.SESSION_TIMEOUT, TimeUnit.MINUTES);
        user.setToken(token);
        return token;
    }

    public static LoginUserDto getLoginUser() {
        if (getRequest() == null) {
            return null;
        }
        String token = getRequest().getHeader("token");
        if (token == null) {
            return null;
        }
        RedisTemplate<String, String> redisTemplateDB = RedisUtils.setConnectionFactoryDB(RequestContext.redisTemplate, 0);
        String json = redisTemplateDB.opsForValue().get(Constants.TOKEN_PREFIX + token);
        if (StringUtils.isBlank(json)) {
            return null;
        }
        return JSON.parseObject(json, LoginUserDto.class);
    }

    public static void refreshToken() {
        String token = getRequest().getHeader("token");
        if (StringUtils.isBlank(token)) {
            return;
        }
        RedisTemplate<String, String> redisTemplateDB = RedisUtils.setConnectionFactoryDB(RequestContext.redisTemplate, 0);
        redisTemplateDB.expire(Constants.TOKEN_PREFIX + token, Constants.SESSION_TIMEOUT, TimeUnit.MINUTES);
    }

    @Resource
    public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
        RequestContext.redisTemplate = redisTemplate;
    }
}
